# -*- coding: UTF-8 -*-

class Loader(object):

    __module_map ={}
    __instance_map = {}


    def __init__(self, core):
        self.core = core


    def module(self, name):
        if not self.__module_map.has_key(name):
            self.__module_map[name] = __import__(name, fromlist=[''])
        return self.__module_map[name]


    def instance(self, moduleName, className, **paramDict):
        instance = self.getInstance(moduleName, className)
        if instance is None:
            if paramDict.get('transport_core', False):
                paramDict['transport_core'] = self.core
            instance = getattr(self.module(moduleName), className)(**paramDict)
            self.saveInstance(moduleName, className, instance)
        return instance


    def reloadModule(self, name):
        self.__module_map[name] = reload(self.__module_map[name]) if self.__module_map.has_key(name) else reload(__import__(name, fromlist=['']))
        return self.__module_map[name]


    def newInstance(self, moduleName, className, **paramDict):
        if paramDict.get('transport_core', False):
            paramDict['transport_core'] = self.core
        instance = getattr(self.module(moduleName), className)(**paramDict)
        self.saveInstance(moduleName, className, instance)
        return instance


    def service(self, className, **paramDict):
        paramDict['transport_core'] = True
        return self._baseLoader('service', className, **paramDict)


    def lib(self, className, **paramDict):
        return self._baseLoader('lib', className, **paramDict)


    def model(self, className, **paramDict):
        paramDict['transport_core'] = True
        return self._baseLoader('model', className, **paramDict)


    def _baseLoader(self, modulePrefix, className, **paramDict):
        moduleName = '%s.%s' % (modulePrefix, className)
        if paramDict.has_key('is_reload'):
            paramDict.pop('is_reload')
            return self.newInstance(moduleName, className, **paramDict)
        else:
            return self.instance(moduleName, className, **paramDict)


    def saveInstance(self, moduleName, className, instance):
        __key = '_'.join([moduleName, className])
        self.__instance_map[__key] = instance


    def getInstance(self, moduleName, className):
        __key = '_'.join([moduleName, className])
        return self.__instance_map[__key] if self.__instance_map.has_key(__key) else None
